package com.gitee.sparta.api;

import java.time.Duration;
import java.util.List;
import java.util.Set;

/**
 * sparta 模板方法，用于用户提交任务到 sparta 3
 * <p>
 * 主要功能：
 * 1. 业务的同步和异步的写入
 * 2. 根据功能区分：
 *  2.1 普通任务
 *  2.2 分段任务
 *  2.3 广播任务
 * 3. 提供 deny 的数据处理 api
 * 4. 提供查询 api
 * 5. 提供删除消息 api
 * <p>
 *  @author zyred
 * @since v 0.0.1
 */
public interface SpartaTemplate<V> {

    /**
     * 同步添加任务到 sparta 中
     *
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param expire    超时时间，单位 ms
     */
    void write (String topic, V val, long expire);

    /**
     * 同步添加任务到 sparta 中，自定义 metaId
     *
     * @param metaId    支持自定义 metaId
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param expire    超时时间，单位 ms
     */
    void write (String metaId, String topic, V val, long expire);

    /**
     * 异步添加任务到 sparta 中
     *
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param expire    超时时间，单位 ms
     */
    void writeAsync (String topic, V val, long expire);

    /**
     * 异步添加任务到 sparta 中，自定义 metaId
     *
     * @param metaId    支持自定义 metaId
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param expire    超时时间，单位 ms
     */
    void writeAsync (String metaId, String topic, V val, long expire);

    /**
     * 同步添加一个消息到 sparta，分段并设置分段消费的时间
     *
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param timeNodes 时间节点，必须遵循 {@see java.time.Duration} 的使用规则
     */
    void write (String topic, V val, Set<String> timeNodes);

    /**
     * 同步添加一个消息到 sparta，分段并设置分段消费的时间，自定义 metaId
     *
     * @param metaId    支持自定义 metaId
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param timeNodes 时间节点，必须遵循 {@see java.time.Duration} 的使用规则
     */
    void write (String metaId, String topic, V val, Set<String> timeNodes);

    /**
     * 同步添加一个消息到 sparta，分段并设置分段消费的时间
     *
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param timeNodes 时间节点，必须遵循 {@see java.time.Duration} 的使用规则
     */
    void write (String topic, V val, List<Duration> timeNodes);

    /**
     * 同步添加一个消息到 sparta，分段并设置分段消费的时间，自定义 metaId
     *
     * @param metaId    支持自定义 metaId
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param timeNodes 时间节点，必须遵循 {@see java.time.Duration} 的使用规则
     */
    void write (String metaId, String topic, V val, List<Duration> timeNodes);

    /**
     * 异步添加一个消息到 sparta，分段并设置分段消费的时间
     *
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param timeNodes 时间节点，必须遵循 {@see java.time.Duration} 的使用规则
     */
    void writeAsync (String topic, V val, Set<String> timeNodes);

    /**
     * 异步添加一个消息到 sparta，分段并设置分段消费的时间，自定义 metaId
     *
     * @param metaId    支持自定义 metaId
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param timeNodes 时间节点，必须遵循 {@see java.time.Duration} 的使用规则
     */
    void writeAsync (String metaId, String topic, V val, Set<String> timeNodes);

    /**
     * 异步添加一个消息到 sparta，分段并设置分段消费的时间
     *
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param timeNodes 时间节点，必须遵循 {@see java.time.Duration} 的使用规则
     */
    void writeAsync (String topic, V val, List<Duration> timeNodes);

    /**
     * 异步添加一个消息到 sparta，分段并设置分段消费的时间，自定义 metaId
     *
     * @param metaId    支持自定义 metaId
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param timeNodes 时间节点，必须遵循 {@see java.time.Duration} 的使用规则
     */
    void writeAsync (String metaId, String topic, V val, List<Duration> timeNodes);

    /**
     * 同步添加一个广播到 sparta 中
     *
     * @param channel   广播的通道，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param expire    超时时间，单位 ms
     */
    void writeBroadcast(String channel, V val, long expire);

    /**
     * 同步添加一个广播到 sparta 中，自定义 metaId
     *
     * @param metaId    支持自定义 metaId
     * @param channel   广播的通道，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param expire    超时时间，单位 ms
     */
    void writeBroadcast(String metaId, String channel, V val, long expire);

    /**
     * 异步添加一个广播到 sparta 中
     *
     * @param channel   广播的通道，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param expire    超时时间，单位 ms
     */
    void writeBroadcastAsync(String channel, V val, long expire);

    /**
     * 异步添加一个广播到 sparta 中，自定义 metaId
     *
     * @param metaId    支持自定义 metaId
     * @param channel   广播的通道，允许字母与下划线组合
     * @param val       消息的内容，可以是任意的一个实体对象
     * @param expire    超时时间，单位 ms
     */
    void writeBroadcastAsync(String metaId, String channel, V val, long expire);

    /**
     * 一次调用，将会返回全量的没有 ack 的数据，并且只要调用该 api
     * metadata_tab 与 deny_tab 中的数据将会全部被删除，生产环境慎用
     *
     * @return  metadata
     */
    List<V> processDenys ();

    /**
     * 查询消息
     *
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param metaId    消息ID，由系统生成，在 @SpartaListener 标注的方法中有返回
     * @return          body
     */
    V select (String topic, String metaId);

    /**
     * 删除消息
     *
     * @param topic     消息所在的主题，允许字母与下划线组合
     * @param metaId    消息ID，由系统生成，在 @SpartaListener 标注的方法中有返回
     * @return          body
     */
    V delete (String topic, String metaId);

}
